package task

import (
	"encoding/json"
	"github.com/sirupsen/logrus"
	"github.com/xuelang-group/sh-solver-scheduler/internal/controller"
	"github.com/xuelang-group/sh-solver-scheduler/internal/domain/entity"
	"github.com/xuelang-group/sh-solver-scheduler/internal/infra"
	"github.com/xuelang-group/sh-solver-scheduler/pkg/platform/k8s"
	"github.com/xuelang-group/sh-solver-scheduler/pkg/server"
	"strings"

	"github.com/gin-gonic/gin"
)

type taskController struct {
}

func NewTaskController() controller.Controller {
	return &taskController{}
}

func (c *taskController) Name() string {
	return "scheduler"
}

func (p *taskController) RegisterRoute(api *gin.RouterGroup) {
	// 创建任务(执行求解器)
	api.POST("/task/create", p.createTask)
	// 停止任务
	api.POST("/task/stop", p.stopTask)
}

type CmdOption struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

type ReqCreateTask struct {
	Name string `json:"name"` // 任务名称
	// 求解配置
	SolverId    string `json:"solverId"` // 求解器id
	ResourceCPU uint   `json:"resourceCPU"`
	ResourceMEM uint   `json:"resourceMEM"`
	// 文件io
	DownloadList []entity.DownloadListItem `json:"downloadList"`
	UploadList   []entity.UploadListItem   `json:"uploadList"`
	// 命令参数列表
	Options []entity.Option `json:"options"`
	// 环境变量类别
	Envs []entity.Env `json:"envs"`
}

type ReqStopTask struct {
	Id string `json:"id"` // 任务id
}

func (c *taskController) createTask(context *gin.Context) {
	body := ReqCreateTask{}

	if err := context.BindJSON(&body); err != nil {
		server.ResponseFailed(context, 0, err)
		return
	}

	logrus.Infof("create task req body: %+v", body)

	// 先获取原生求解器定义
	solverSpec, err := infra.GetSolverSpec(body.SolverId)
	if err != nil {
		server.ResponseFailed(context, 0, err)
		return
	}

	logrus.Infof("get solver spec: %+v", solverSpec)

	// 获取（创建）新的任务id
	taskSpecJson, err := json.Marshal(body)
	var resultAddr []string
	//resultOssPrefix := infra.GetConfig().OSS.Endpoint + "/" + infra.GetConfig().OSS.Bucket
	for _, value := range body.UploadList {
		//resultAddr = append(resultAddr, resultOssPrefix+"/"+value.OssPath)
		resultAddr = append(resultAddr, value.OssPath)
	}
	taskId, err := infra.GetNewSolverTaskId(body.Name, "queuing", body.SolverId,
		body.ResourceCPU, body.ResourceMEM, strings.Join(resultAddr, ","), string(taskSpecJson))
	if err != nil {
		server.ResponseFailed(context, 0, err)
		return
	}

	// 构建求解器任务实体
	solverTask := &entity.SolverTask{
		ID:           taskId,
		Name:         body.Name, // 任务名字
		DownloadList: body.DownloadList,
		UploadList:   body.UploadList,
		ResourceCPU:  body.ResourceCPU,
		ResourceMEM:  body.ResourceMEM,
		Options:      body.Options,
		Envs:         body.Envs,

		// append others
		Namespace: "sh-dc",
		Status:    "running",

		SolverSpec: solverSpec,
	}

	// 拼装求解器任务运行pod定义
	pod, err := GetSolverTaskPod(solverTask)
	if err != nil {
		server.ResponseFailed(context, 0, err)
		return
	}

	// 创建pod
	_, err = k8s.Client().CreatePod(pod)
	if err != nil {
		server.ResponseFailed(context, 0, err)
		infra.UpdateSolverTaskStatus(taskId, entity.TaskStatusFailed)
		return
	}

	// 设置task状态为运行中
	infra.UpdateSolverTaskStatus(taskId, entity.TaskStatusRunning)

	server.ResponseSuccess(context, map[string]interface{}{
		"taskID": taskId,
	})
}

func (c *taskController) stopTask(context *gin.Context) {
	body := ReqStopTask{}

	if err := context.BindJSON(&body); err != nil {
		server.ResponseFailed(context, 0, err)
		return
	}

	logrus.Infof("stop task req body: %+v", body)
	_ = k8s.Client().DeletePod("sh-dc", body.Id)

	server.ResponseSuccess(context, map[string]interface{}{
		"taskID": body.Id,
	})
}
